package cn.iocoder.yudao.module.engine.service.core.filter.read;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.engine.enums.EnumAudioType;
import cn.iocoder.yudao.module.engine.model.config.ThreeAxisSensorRangeConfig;
import cn.iocoder.yudao.module.engine.model.context.ControlEngineContext;
import cn.iocoder.yudao.module.engine.model.context.SensorStatusContext;
import cn.iocoder.yudao.module.engine.model.engine.EngineInputData;
import cn.iocoder.yudao.module.engine.service.core.filter.read.base.AbstractThreeAxisSensor2AudioFilter;
import cn.iocoder.yudao.module.engine.service.log.IEngineLogService;
import cn.iocoder.yudao.module.infra.api.config.IConfigApi;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;

@Slf4j
@Component
public class ThreeAxisSensorRange2AudioFilter extends AbstractThreeAxisSensor2AudioFilter {
    private static final String CONFIG_KEY_SPEED = "sensor.speed.config";
    private static final String CONFIG_KEY_MAX_CHANGE_MIN_VALUE = "sensor.three_axis.max_change_min_value";

    @Resource
    private IConfigApi configApi;

    @Resource
    private IEngineLogService logService;

    @Override
    public EnumAudioType getAudioType() {
        return EnumAudioType.THREE_AXIS_RANGE;
    }

    @Override
    public List<String> triggerThreeAxisSensor(ControlEngineContext engineContext, EngineInputData.Sensor sensor) {
        final String speedConfigString = configApi.getValueByKey(CONFIG_KEY_SPEED);
        final ThreeAxisSensorRangeConfig speedConfig = JsonUtils.parseObject(speedConfigString, ThreeAxisSensorRangeConfig.class);

        final SensorStatusContext.TreeAxisRange status = engineContext.getSynStatusCtx().getSensorStatusContext().getTreeAxisRange();

        final List<String> newTags = findSpeedTagName(engineContext, speedConfig, sensor);

        status.setLastTriggerTime(System.currentTimeMillis());
        status.setLastTriggerXAxis(sensor.getXAxis());
        status.setLastTriggerYAxis(sensor.getYAxis());
        status.setLastTriggerZAxis(sensor.getZAxis());
        engineContext.getSynStatusCtx().syn();
        log.info("三轴传感器坐标幅度-更新传感器状态：{}", status);

        return newTags;
    }

    private List<String> findSpeedTagName(ControlEngineContext engineContext, ThreeAxisSensorRangeConfig speedConfig, EngineInputData.Sensor sensor) {
        final SensorStatusContext.TreeAxisRange status = engineContext.getSynStatusCtx().getSensorStatusContext().getTreeAxisRange();
        List<String> newTags = null;

        // 变动幅度
        final int xAxisChange = status.getLastTriggerXAxis() == 0 ? 0 : Math.abs(Math.abs(sensor.getXAxis()) - Math.abs(status.getLastTriggerXAxis()));
        final int yAxisChange = status.getLastTriggerYAxis() == 0 ? 0 : Math.abs(Math.abs(sensor.getYAxis()) - Math.abs(status.getLastTriggerYAxis()));
        final int zAxisChange = status.getLastTriggerZAxis() == 0 ? 0 : Math.abs(Math.abs(sensor.getZAxis()) - Math.abs(status.getLastTriggerZAxis()));
        final int currentAxisChange = NumberUtil.max(xAxisChange, yAxisChange, zAxisChange);

        final Integer historyMaxChange = engineContext.getSessionCtx().getUserPreferenceCtx().getThreeAxisSensorMaxChange();
        final Integer historyMaxChangeRequiredMinValue = Integer.parseInt(configApi.getValueByKey(CONFIG_KEY_MAX_CHANGE_MIN_VALUE));
        if (historyMaxChange > 0 && historyMaxChange > historyMaxChangeRequiredMinValue) {
            // 百分比
            final int currentPercentage = currentAxisChange * 100 / historyMaxChange;
            final List<ThreeAxisSensorRangeConfig.Percentage> percentages = speedConfig.getPercentages();
            for (ThreeAxisSensorRangeConfig.Percentage percentage : percentages) {
                if (percentage.getMin() != null && currentPercentage < percentage.getMin()) {
                    continue;
                }
                if (percentage.getMax() != null && currentPercentage > percentage.getMax()) {
                    continue;
                }
                newTags = percentage.getTags();
            }

            log.info("三轴传感器坐标幅度-匹配标签-百分比, maxAxisChange = {}, historyMaxChange = {}, currentPercentage = {}, xAxisChange = {}, yAxisChange = {}, zAxisChange = {}, newTags = {}",
                    currentAxisChange, historyMaxChange, currentPercentage, xAxisChange, yAxisChange, zAxisChange, newTags);
            if (CollUtil.isNotEmpty(newTags)) {
                logService.log(engineContext, StrUtil.format("【三轴传感器坐标幅度已触发】百分比匹配 [百分比]: {}, [当前幅度]: {}, 历史最大幅度]: {}, [闭合次数]: {}, [X轴]: {}, [Y轴]: {}, [Z轴]: {}, [标签]: {}",
                        currentPercentage, currentAxisChange, historyMaxChange, sensor.getUpCount(), sensor.getXAxis(), sensor.getYAxis(), sensor.getZAxis(), newTags));
            } else {
                logService.log(engineContext, StrUtil.format("【三轴传感器坐标幅度未触发】百分比匹配 [百分比]: {}, [当前幅度]: {}, 历史最大幅度]: {}, [闭合次数]: {}, [X轴]: {}, [Y轴]: {}, [Z轴]: {}, [标签]: {}",
                        currentPercentage, currentAxisChange, historyMaxChange, sensor.getUpCount(), sensor.getXAxis(), sensor.getYAxis(), sensor.getZAxis(), newTags));
            }
        } else {
            // 区间
            final List<ThreeAxisSensorRangeConfig.UpCountRange> ranges = speedConfig.getRanges();
            for (ThreeAxisSensorRangeConfig.UpCountRange upCountRange : ranges) {
                // max/max都可能为空， 如果某一个值为空表示不限制
                if (upCountRange.getAxisChangeMin() != null && currentAxisChange < upCountRange.getAxisChangeMin()) {
                    continue;
                }
                if (upCountRange.getAxisChangeMax() != null && currentAxisChange > upCountRange.getAxisChangeMax()) {
                    continue;
                }

                newTags = upCountRange.getTags();
                break;
            }

            log.info("三轴传感器坐标幅度-匹配标签-区间, historyMaxChange = {}, historyMaxChangeRequiredMinValue = {}, currentAxisChange = {}, xAxisChange = {}, yAxisChange = {}, zAxisChange = {}, newTags = {}",
                    historyMaxChange, historyMaxChangeRequiredMinValue, currentAxisChange, xAxisChange, yAxisChange, zAxisChange, newTags);
            if (CollUtil.isNotEmpty(newTags)) {
                logService.log(engineContext, StrUtil.format("【三轴传感器坐标幅度已触发】区间匹配 [闭合次数]: {}, [变动幅度]: {}, [X轴]: {}, [Y轴]: {}, [Z轴]: {}, [标签]: {}",
                        sensor.getUpCount(), currentAxisChange, sensor.getXAxis(), sensor.getYAxis(), sensor.getZAxis(), newTags));
            } else {
                logService.log(engineContext, StrUtil.format("【三轴传感器坐标幅度未触发】区间匹配 [闭合次数]: {}, [变动幅度]: {}, [X轴]: {}, [Y轴]: {}, [Z轴]: {}, [标签]: {}",
                        sensor.getUpCount(), currentAxisChange, sensor.getXAxis(), sensor.getYAxis(), sensor.getZAxis(), newTags));
            }
        }

        if (currentAxisChange > historyMaxChange) {
            engineContext.getSessionCtx().getUserPreferenceCtx().setThreeAxisSensorMaxChange(currentAxisChange);
            log.info("更新三轴传感器最大变动幅度, currentAxisChange = {}, historyMaxChange = {}", currentAxisChange, historyMaxChange);
        }

        return newTags;
    }

}
